#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logs, time

from ..lib.plugin import MeliponiniPlugin
from ..lib.config import Config
#from ..lib.utils import Utils

config = Config()

NODESFILE = '/etc/meliponini/nodes'

def log(s):
    logs.log(s)



'''
Obtiene los nodos de esta botnet
'''
def getNodes():
    nodes = []
    try:
        f = open(NODESFILE, 'r')
        nodes = [line.strip(' \n').split(':') for line in f]
        f.close()
    except IOError:
        log( "ERROR: cannot read nodes file: %s" % NODESFILE ) 

    return nodes


'''
Actualiza uno de los nodos de nuestra botnet
'''
def updateNode(nhost, nport, nuser, npass):
    nodes = getNodes()
    f = open(NODESFILE, 'w')
    for node in nodes:
        if node[0] == nhost:
            node[1] = nport
            node[2] = nuser
            node[3] = npass
        f.write( ':'.join(node) + "\n" )
    f.close()


'''
Guarda información de un nodo de la botnet
'''
def saveNode(nhost, nport, nuser, npass):
    # buscamos el host en nuestra botnet
    for node in getNodes():
        if node[0] == nhost:
            updateNode(nhost, nport, nuser, npass)
            return
    
    # el nodo no está en la lista
    # lo añadimos
    f = open(NODESFILE, 'a')
    f.write("%s:%s:%s:%s\n" % (nhost, nport, nuser, npass))
    f.close()
    
    '''
    # TODO: ...
    # enviamos este cambio a toda la botnet,
    #    menos al host que se está guardando,
    #    menos a nosotros mismos
    for node in getNodes():
        (bhost, bip, bport, buser, bpass) = node
        if bhost != nhost:
            doPOST(bhost, bport, buser, bpass, '/ping/', {
                'host': nhost,
                'ip':   nip,
                'port': nport,
                'user': nuser,
                'pass': npass
            })
    '''
        
    return



class plugin(MeliponiniPlugin):
    def constructor(self, method):
        #self.directory = config.get('dirs.www')
        
        #if method == 'get':
        #    self.addHTTPHandler('/www/list/', self.commandList)
        #    self.addHTTPHandler('/www/backup/', self.commandBackup)
            
        self.addTimer(60, self.timerCheckService)
        
        
    '''
    TIMER checkService
    Comprueba que el servicio Apache esté levantado
    '''
    def timerCheckService(self):
        return

    '''
    POST /node/ping/
    host={host}&port={port}&user={user}&pass={pass}
    Recepción de ping.
    Debemos registrar el nodo que nos envía el ping en nuestra lista local de nodos.
    Devolvemos el "status", compuesto de la lista local de nodos, versión del
    software del nodo, tamaño y fecha de cada uno de los ficheros fuente de este
    nodo, etc.
    '''
    def commandPing(self):
        # obtenemos lista local de nodos de la botnet
        nodes = getNodes()
        
        # obtenemos listado de los fuentes del nodo
        dirname = sys.path[0]
        sources = []
        for filename in ['config.py','handler.py','serverpanel.py','serverpaneld.py']:
            status = os.stat(dirname + '/' + filename)
            sources.append({
                'filename': filename,
                'size': status.st_size,
                'time': status.st_mtime
            })
            
        # añadimos el nodo que hace la petición a la lista local de nodos
        # Parse the form data posted
        form = cgi.FieldStorage(
            fp = self.rfile, 
            headers = self.headers,
            environ = {
                'REQUEST_METHOD': 'POST',
                'CONTENT_TYPE': self.headers['Content-Type'],
            }
        )
        
        # obtenemos variables POST
        vhost=vport=vuser=vpass=""
        if form.has_key('host'):
            vhost = form['host'].value
        if form.has_key('port'):
            vport = form['port'].value
        if form.has_key('user'):
            vuser = form['user'].value
        if form.has_key('pass'):
            vpass = form['pass'].value
            
        # guardamos información del nodo
        saveNode(vhost, vport, vuser, vpass)
        
        # devolvemos los datos de estado en JSON
        self.responseJSON({
            'version': self.config.VERSION,
            'nodes': nodes,
            'sources': sources
        })
        
        
    
    '''
    POST /node/add/
    host={host}&port={port}&user={user}&pass={pass}
    Añadimos un nodo a la lista de nodos de nuestra botnet.
    Al añadir un nuevo nodo conseguimos que este nodo entre a formar parte de la
    netbot de ese nodo, ya que cuando este nodo le haga PING obtendrá el listado
    completo de nodos de la netbot, sobre los que podrá operar.
    '''
    def commandAdd(self):
        # añadimos el nodo que hace la petición a la lista local de nodos
        # Parse the form data posted
        form = cgi.FieldStorage(
            fp = self.rfile, 
            headers = self.headers,
            environ = {
                'REQUEST_METHOD': 'POST',
                'CONTENT_TYPE': self.headers['Content-Type'],
            }
        )
        
        # obtenemos variables POST
        if form.has_key('host'):
            vhost = form['host'].value
            if form.has_key('port'):
                vport = form['port'].value
                if form.has_key('user'):
                    vuser = form['user'].value
                    if form.has_key('pass'):
                        vpass = form['pass'].value
                        # guardamos información del nodo
                        saveNode(vhost, vport, vuser, vpass)

        self.responseJSON(getNodes())
        